<?php
/**
 * Created by PhpStorm.
 * User: whwyy
 * Date: 2018/3/30 0030
 * Time: 15:23
 */

namespace Database;

use Database\base\DbBase;
use Database\base\DbException;


/**
 * Class Command
 * @package Database
 */
class Command extends DbBase
{
    /** @var \PDO */
    public $pdo;

    /** @var string */
    public $sql = '';

    /** @var array */
    public $params = [];

    /** @var bool */
    private $isFail = TRUE;

    /** @var \PDOStatement */
    private $prepare;

    /**
     * @return bool|\PDOStatement
     * @throws
     */
    private function query()
    {
        $this->prepare = $this->pdo->prepare($this->sql);
        if (!$this->prepare) {
            throw new DbException($this->pdo->errorInfo()[2]);
        }
        foreach ($this->params as $key => $val) {
            if (is_array($val)) {
                throw new DbException("Save data cannot have array");
            }
            $this->bindParam(':' . $key, $val);
        }
        return $this->prepare;
    }

    /**
     * @param bool $isInsert
     * @return bool|string
     * @throws
     */
    public function save($isInsert = TRUE)
    {
        $exec = $this->query()->execute();
        if (!$exec) {
            return $this->addError($this->getError(), 'mysql');
        }
        $this->prepare->closeCursor();
        if ($isInsert) {
            return $this->pdo->lastInsertId() ?? TRUE;
        } else {
            return TRUE;
        }
    }


    /**
     * @return bool|int
     * @throws \Exception
     */
    public function all()
    {
        return $this->execute('fetchAll');
    }

    /**
     * @return array|mixed
     * @throws \Exception
     */
    public function one()
    {
        return $this->execute('fetch');
    }

    /**
     * @return bool|int
     * @throws \Exception
     */
    public function fetchColumn()
    {
        $result = $this->execute('fetchColumn');
        if (!is_array($result)) {
            return (bool)$result;
        }
        return array_shift($result) == NULL;
    }

    /**
     * @return bool|int
     * @throws \Exception
     */
    public function rowCount()
    {
        return $this->execute('rowCount');
    }

    /**
     * @param $type
     * @return bool|int
     * @throws \Exception
     */
    private function execute($type)
    {
        $pdo = $this->query();
        if (!$this->isFail) return FALSE;
        if (!$pdo->execute()) {
            return $this->addError($this->getError(), 'mysql');
        }
        if ($type == 'rowCount') {
            $result = $pdo->rowCount();
        } else {
            $result = $pdo->$type(\PDO::FETCH_ASSOC);
        }
        $pdo->closeCursor();
        return $result;
    }

    /**
     * @param $type
     * @return bool|int
     * @throws \Exception
     */
    public function delete()
    {
        return $this->query()->execute();
    }

    /**
     * @param $name
     * @param $value
     */
    public function bindParam($name, $value)
    {
        $this->prepare->bindValue($name, $value);
    }

    /**
     * @return $this
     */
    public function bindValues(array $data = NULL)
    {
        $this->isFail = TRUE;
        if (empty($this->params)) {
            return $this;
        }
        if (!empty($data)) {
            $this->params = array_merge($this->params, $data);
        }
        return $this;
    }

    /**
     * @return string
     */
    public function getError()
    {
        return $this->prepare->errorInfo()[2] ?? '系统繁忙. 请稍后再试.';
    }
}